#==============================================================================
#
#  $Id: minicl.py,v 1.2 2002/03/09 19:54:16 mike Exp $
#
"""
   Contains the @MiniComLine class.
"""
#
#  Copyright (C) 2001 Michael A. Muller
#
#  Permission is granted to use, modify and redistribute this code,
#  providing that the following conditions are met:
#
#  1) This copyright/licensing notice must remain intact.
#  2) If the code is modified and redistributed, the modifications must 
#  include documentation indicating that the code has been modified.
#  3) The author(s) of this code must be indemnified and held harmless
#  against any damage resulting from the use of this code.
#
#  This code comes with ABSOLUTELY NO WARRANTEE, not even the implied 
#  warrantee of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
#
#==============================================================================

from dopy import Reactor, getHub
import sys, traceback, thread, Queue

class MiniComLine(Reactor):
   """
      This class defines a tiny python command line reactor, which can
      be useful for controlling a server.
   """

   def __init__(self):
      # sort of a hack: display the first prompt because we won't be
      # able to do anything until we are notified that standard input
      # is ready for read.
      self.doPrompt()
      
      self.context = {}

      if getHub().isThreaded():
         self.__q = Queue.Queue(0)
         thread.start_new_thread(self.__execThread, ())
      else:
         self.__q = None
   
   def fileno(self):
      "implements @dopy.dopy.Reactor.fileno()"
      return sys.stdin.fileno()
   
   def notifyWhenReadable(self):
      "implements @dopy.dopy.Reactor.notifyWhenReadable()"
      return 1
   
   def notifyWhenWritable(self):
      "implements @dopy.dopy.Reactor.notifyWhenWritable()"
      return 0
   
   def notifyOnError(self):
      "implements @dopy.dopy.Reactor.notifyOnError()"
      return 1
   
   def doPrompt(self):
      """
         Displays a nice "dopy>" prompt indicating that the user can
         enter data.
      """
      sys.stdout.write('dopy> ')
      sys.stdout.flush()
   
   def __execLine(self, line):
      """
         Executes a single line, handles execptions and displays the
         prompt again when done.
      """
      try:
         exec line in self.context
      except Exception, ex:
         traceback.print_exc(sys.exc_info())
      self.doPrompt()
   
   def __execThread(self):
      """
         This method watches a queue for input lines, handling their
         exceptions and printing the prompt when done executing.
      """
      while 1:
         line = self.__q.get()
         self.__execLine(line)
   
   def handleRead(self):
      "implements @dopy.dopy.Reactor.handleRead()"
      line = sys.stdin.readline()
      if self.__q:
         self.__q.put(line)
      else:
         self.__execLine(line)

   def handleWrite(self):
      "implements @dopy.dopy.Reactor.handleWrite()"
      pass
   
   def handleError(self):
      "implements @dopy.dopy.Reactor.handleWrite()"
      pass
